from sqlalchemy import create_engine, MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, INT, Boolean, ForeignKey, Float
from sqlalchemy import DateTime, BigInteger, DateTime, Numeric
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.orm import relationship
from sqlalchemy import event
import config
import time


def get_session(db_url):
    engine = create_engine(
        db_url, pool_size=20, pool_recycle=3600, pool_timeout=3600)
    metadata = MetaData()
    return (engine, scoped_session(
        sessionmaker(autocommit=False, autoflush=False, bind=engine)))


(pg_engine, pg_db_session) = get_session(config.PG_DATABASEURI)

Base = declarative_base()

#pg_engine.execute("SET search_path TO mondo")


class report():
    ip = Column(String(15), primary_key=True)
    metric = Column(String(800), primary_key=True)
    submetric = Column(String(800), primary_key=True)
    path = Column(String(800), primary_key=True)
    flag = Column(String(80), primary_key=True)
    value = Column(Float)
    strvalue = Column(String(800))
    contact = Column(INT)

    def __init__(ip, metric, submetric, path, flag, value, strvalue, contact):
        self.ip = ip
        self.metric = metric
        self.submetric = submetric
        self.path = path
        self.flag = flag
        self.value = value
        self.strvalue = strvalue
        self.contact = contact


class taskstatus(Base):
    __tablename__ = 'taskstatus'
    ip = Column(String(15), primary_key=True)
    clientuid = Column(String(100), primary_key=True)
    module = Column(String(200), primary_key=True)
    start = Column(Boolean, primary_key=True)
    result = Column(String(500), nullable=True)
    error = Column(String(500), nullable=True)
    contact = Column(INT, primary_key=True)


class statusreport(Base):
    __tablename__ = 'statusreport'
    ip = Column(String(15), primary_key=True)
    metric = Column(String(800), primary_key=True)
    submetric = Column(String(800), primary_key=True)
    start = Column(INT, primary_key=True)
    end = Column(INT, primary_key=True)
    value = Column(Float)
    strvalue = Column(String(800))
    contact = Column(INT)


class hardwaremetric(Base):
    __tablename__ = 'hardwaremetric'
    ip = Column(String(15), primary_key=True)
    name = Column(String(800), primary_key=True)
    contact = Column(INT, primary_key=True)
    value = Column(BigInteger)


class hardwareinfo(Base):
    __tablename__ = 'hardwareinfo'
    ip = Column(String(15), primary_key=True)
    name = Column(String(800), primary_key=True)
    contact = Column(INT, primary_key=True)
    value = Column(String(1200))


class passwdlist(Base):
    __tablename__ = 'passwdlist'
    ip = Column(String(15), primary_key=True)
    password = Column(String(100), primary_key=True)
    contact = Column(INT, primary_key=True)


class commonheartbeatview(Base):
    __tablename__ = 'commonheartbeatview'
    ip = Column(String(15), primary_key=True)
    source = Column(String(100), primary_key=True)
    state = Column(String(100), primary_key=True)
    contact = Column(DateTime(timezone=True), primary_key=True)


class commonheartbeat(Base):
    __tablename__ = 'commonheartbeat'
    ip = Column(String(15), primary_key=True)
    source = Column(String(100), primary_key=True)
    state = Column(String(100), primary_key=True)
    contact = Column(INT, primary_key=True)


@event.listens_for(hardwaremetric, "before_insert")
def gen_default(mapper, connection, instance):
    instance.contact = int(time.time())


@event.listens_for(hardwareinfo, "before_insert")
def gen_default(mapper, connection, instance):
    instance.contact = int(time.time())


@event.listens_for(passwdlist, "before_insert")
def gen_default(mapper, connection, instance):
    instance.contact = int(time.time())


@event.listens_for(statusreport, "before_insert")
def gen_default(mapper, connection, instance):
    instance.contact = int(time.time())


@event.listens_for(commonheartbeat, "before_insert")
def gen_default(mapper, connection, instance):
    instance.contact = int(time.time())


@event.listens_for(taskstatus, "before_insert")
def gen_taskstatus(mapper, connection, instance):
    instance.contact = int(time.time())


# Base.metadata.create_all(pg_engine)
def create_if_not_exist(tbname):
    for x in Base.__subclasses__():
        if x.__name__ == tbname:
            return x
    tbclz = type(tbname, (Base, report), {'__tablename__': tbname})
    tbclz.__table__.create(pg_engine, checkfirst=True)
    return tbclz